/*
 * F-List Pidgin - a libpurple protocol plugin for F-Chat
 *
 * Copyright 2011 F-List Pidgin developers.
 *
 * This file is part of F-List Pidgin.
 *
 * F-List Pidgin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * F-List Pidgin is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with F-List Pidgin.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "f-list_icon.h"

#define FLIST_REQUESTS_PER_SECOND 8 //TODO: implement this!
#define FLIST_MAX_ICON_REQUESTS 4

typedef struct FListFetchIcon_ {
    PurpleUtilFetchUrlData *url_data;
    PurpleConnection *pc;
    gchar *character;
} FListFetchIcon;

static void flist_fetch_icon_real(PurpleConnection *, const gchar *);

static void flist_fetch_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer data, const gchar *b, size_t len, const gchar *err) {
    FListFetchIcon *fli = data;
    PurpleConnection *pc = fli->pc;
    PurpleAccount *pa = purple_connection_get_account(pc);
    FListAccount *fla = pc->proto_data;
    const gchar *character, *checksum;

    checksum = "0"; /* what the fuck is this checksum supposed to be?? */
    character = fli->character;

    if(err) {
        //TODO: handle this error message?
        return;
    } else {
        purple_buddy_icons_set_for_user(pa, character, g_memdup(b, len), len, checksum);
    }

    fla->icon_requests = g_slist_remove(fla->icon_requests, fli);

    g_free(fli->character);
    g_free(fli);

    gboolean done = FALSE;
    while(fla->icon_request_queue && !done) {
        gchar *name = fla->icon_request_queue->data;
        if(purple_find_buddy(pa, name)) {
            flist_fetch_icon_real(pc, fla->icon_request_queue->data);
            done = TRUE;
        }
        fla->icon_request_queue = g_slist_delete_link(fla->icon_request_queue, fla->icon_request_queue);
        g_free(name);
    }
}

static void flist_fetch_icon_real(PurpleConnection *pc, const gchar *character) {
    FListAccount *fla = pc->proto_data;
    FListFetchIcon *fli = g_new0(FListFetchIcon, 1);
    PurpleUtilFetchUrlData *url_data;
    gchar *character_lower;
    gchar *url;

    character_lower = g_utf8_strdown(character, -1);
    url = g_strdup_printf("http://static.f-list.net/images/avatar/%s.png", purple_url_encode(character_lower));
    url_data = purple_util_fetch_url_request(url, TRUE, USER_AGENT, TRUE, NULL, FALSE, flist_fetch_icon_cb, fli);

    fli->pc = pc;
    fli->character = g_strdup(character);
    fli->url_data = url_data;
    fla->icon_requests = g_slist_prepend(fla->icon_requests, fli);
    g_free(url);
    g_free(character_lower);
}

void flist_fetch_icon(PurpleConnection *pc, const gchar *character) {
    FListAccount *fla = pc->proto_data;
    int len;

    //TODO: show some restraint!

    len = g_slist_length(fla->icon_requests);
    if(len < FLIST_MAX_ICON_REQUESTS) {
        flist_fetch_icon_real(pc, character);
    } else {
        fla->icon_request_queue = g_slist_append(fla->icon_request_queue, g_strdup(character));
    }
}

void flist_fetch_icon_cancel_all(PurpleConnection *pc) {
    FListAccount *fla = pc->proto_data;
    GSList *req;

    req = fla->icon_requests;
    while(req) {
        FListFetchIcon *fli = req->data;
        g_free(fli->character);
        purple_util_fetch_url_cancel(fli->url_data);
        g_free(fli);
        req = g_slist_next(req);
    }
    g_slist_free(fla->icon_requests);
    fla->icon_requests = NULL;

    req = fla->icon_request_queue;
    while(req) {
        g_free(req->data);
        req = g_slist_next(req);
    }
    fla->icon_request_queue = NULL;
}
